#include <iostream>
#include <vector>
# include <windows.h>
#include "./include/rapidjson/document.h"
#include "./include/rapidjson/writer.h"

using namespace std;
using namespace rapidjson;

const string userNamePre = "测试名称 c++/go/cangjie 编程语言 json序列化、反序列化性能大比拼 - ";
float scoreBase = 65.5;
int ageBase = 18;

class Stu {
public :
    string name;
    int sex;
    int age;
    float score;

    Stu(string name, int sex, int age, float score) : name(name), sex(sex), age(age), score(score) {};
};

// 将结构体转为 json 文档值
void StuToJson(unique_ptr<Stu> &stu, Value &value, Document::AllocatorType &allocator) {
    value.SetObject();
    Value val;

    value.AddMember("name", Value(StringRef(stu->name.c_str()), allocator), allocator);
    value.AddMember("sex", val.SetInt(stu->sex), allocator);
    value.AddMember("age", val.SetInt(stu->age), allocator);
    value.AddMember("score", val.SetFloat(stu->score), allocator);
}

// 构建 json 文档结构
Document BuildJsonDocument(Value &listData, Document::AllocatorType &allocator) {
    Document document;
    document.SetObject();

    Value value;
    document.AddMember("code", value.SetInt(200), allocator);
    document.AddMember("msg", value.SetString("成功"), allocator);
    document.AddMember("list", listData, allocator);

    return document;
}

// 将 json文档序列化为文本(string)
string JsonEncode(const Document &jsonDoc) {
    StringBuffer buffer;
    // 创建Writer对象，将document写入到buffer中
    Writer<StringBuffer> writer(buffer);
    jsonDoc.Accept(writer);
    return buffer.GetString();
}


// 初始化 N 个对象数组
void InitStu(int num, Value &valueArr, Document::AllocatorType &allocator) {
    for (int i = 0; i < num; i++) {
        unique_ptr<Stu> tmpStu(new Stu(userNamePre + to_string(i), i % 2, ageBase + i, scoreBase + float(i)));
        // 将普通对象转为 value 对象
        Value tmpValueObj(kObjectType);
        StuToJson(tmpStu, tmpValueObj, allocator);
        valueArr.PushBack(tmpValueObj, allocator);
    }
}

int main() {
    DWORD startSec = GetTickCount();

    // 创建一个Document对象，它是一个空的JSON对象
    Document document;
    Document::AllocatorType &allocator = document.GetAllocator();

    Value valueArr(kArrayType);
    int rows = 1000000;     // 初始化 100 万个对象
    valueArr.Reserve(rows, document.GetAllocator());

    InitStu(rows, valueArr, allocator);

    //构建 json 文档结构
    Document jsonDoc = BuildJsonDocument(valueArr, allocator);

    // 将100万行json文档序列化、反序列化10次
    string jsonStr;
    for (int i = 0; i < 10; i++) {
        // json 文档序列化为 json 文本
        jsonStr = JsonEncode(jsonDoc);
    }

    DWORD useMillionSecond = (GetTickCount() - startSec) / 10;

    cout << "100万个对象(Stu) json序列化性能测试对比，单次平均耗时(ms)：" << useMillionSecond << endl;
    // std::cout << jsonStr << std::endl;
    cout << "json-string 的总长度：" << jsonStr.length() << endl;

    return 0;
}
